# -*- coding: UTF-8 -*-
# version 1.0
# Ip网络 Server层
import json, math

from mxsoftpy import Server
from index import _
from db.common.NetworkManage.IpAM.IpNetwork import IpNetworkDB
from model.common.NetworkManage.IpAM.IpNetwork import IpNetworkModel
from functools import reduce
from mxsoftpy.exception import ParamsError


class IpNetworkServer(Server):
    __model__ = IpNetworkModel
    __db__ = IpNetworkDB

    def list_tree1(self, data, parent_column="parent_code", child_column="children", parent="0", data_tree_list={},
                   level=0):
        """

        :param data:
        :param parent_column:
        :param child_column:
        :param parent:
        :param data_tree_list:
        :return:
        """
        for d_id, d_dic in data.items():
            pid = d_dic.get(parent_column)  # 取每一个字典中的父id
            if not pid or pid == parent:  # 父id=0，就直接加入数据大列表
                d_dic['level'] = level + 1
                data[pid][child_column].append(d_dic)
                self.list_tree1(data, parent_column, child_column, d_dic['id'], data_tree_list,d_dic['level'])

    def list_to_trees(self, data, parent_column="parent_code", child_column="children", parent="0", current_column=None,
                      current_path=None):
        """
        将数据转换为树结构
        :param data: 数据字典
                    eg:
                        {"1": {"name": "测试视频组", "parent_code": 0},
                         "2": {"name": "测试视频组", "parent_code": 1},
                         "3": {"name": "测试视频组", "parent_code": 0},
                         "4": {"name": "测试视频组", "parent_code": 1},
                         "5": {"name": "测试视频组", "parent_code": 1},
                         "6": {"name": "测试视频组", "parent_code": 5}}
        :param parent_column: 父ID字段名，父ID默认为0
        :param child_column: 子列表字典名称
        :param current_column: 当前展开值字段名，若找到展开值增加["open"] = "1"
        :param current_path: 当前展开值
        :return: 树结构
        """
        data_tree_list = []  # 整个数据大列表
        for d_id, d_dic in data.items():
            pid = d_dic.get(parent_column)  # 取每一个字典中的父id
            if not pid or pid == parent:  # 父id=0，就直接加入数据大列表
                d_dic['level'] = 1
                data_tree_list.append(d_dic)

        for val in data_tree_list:
            self.list_tree1(data, parent_column, child_column, val['id'], data_tree_list, val['level'])
        # for d_id, d_dic in data.items():
        #     pid = d_dic.get(parent_column)  # 取每一个字典中的父id
        #     if not pid or pid == parent:  # 父id=0，就直接加入数据大列表
        #         pass
        #     else:  # 父id>0 就加入父id队对应的那个的节点列表
        #         try:  # 判断异常代表有子节点，增加子节点列表=[]
        #             d_dic['level'] = data[pid]['level'] + 1
        #             data[pid][child_column].append(d_dic)
        #         except KeyError:
        #             print(d_dic)
        #             data[pid][child_column] = []
        #             data[pid][child_column].append(d_dic)
        #             # continue

        return data_tree_list

    def create(self, *args, **kwargs):
        """
        添加IP子网数据
        :param args:
        :param kwargs:  添加数据 字典
        :return:
        """
        return self.db.create(**kwargs)

    def list_tree(self, group, subnet, key, subnet_count, GroupId, network):
        """
        树
        :param group: 组
        :param subnet: 子健
        :param key: ID
        :param subnet_count: 子网
        :param GroupId: 组ID
        :return:
        """
        group_dict = sorted(group.items(), key=lambda k: int(k[0][6:]), reverse=False)
        res = dict()
        tmp = list()
        UnTrustIpCount_dict = dict()
        for v in group_dict:
            # 判断组存在删除组
            if v[0] == GroupId and key == network:
                continue
            v[1]['issubnet'] = 0
            subtree = list()
            if subnet:
                for k, val in subnet.items():
                    if 'GroupId' in val and val['GroupId']:
                        if val['GroupId'] == v[0]:
                            if k not in subnet_count:
                                raise ParamsError(_('获取缓存%s失败' % k))
                            count_int = subnet_count[k]['UsedIpCount'] if k in subnet_count else 0
                            UnTrustIp_int = subnet_count[k]['UnTrust']
                            label = val['label'] if val['label'] else k
                            subtree.append({'id': k, 'name': label, 'SubnetIp': val['SubnetIp'], 'type': '2',
                                            'parent': val['GroupId'], 'count': count_int, 'network': key,
                                            'UnTrustIp': UnTrustIp_int, 'logicId': key + 'mx' + k,
                                            'logicpid': key + 'mx' + val['GroupId']})
                            UnTrustIpCount_dict[k] = UnTrustIp_int
                            v[1]['issubnet'] = 1
                    else:
                        if k not in subnet_count:
                            raise ParamsError(_('获取缓存%s失败' % k))
                        count_int = subnet_count[k]['UsedIpCount'] if k in subnet_count else 0
                        UnTrustIp_int = subnet_count[k]['UnTrust']
                        label = val['label'] if val['label'] else k
                        tmp.append(
                            {'id': k, 'name': label, 'SubnetIp': val['SubnetIp'], 'type': '2', 'parent': key,
                             'count': count_int, 'network': key, 'UnTrustIp': UnTrustIp_int, 'logicId': key + k,
                             'logicpid': key})
                        UnTrustIpCount_dict[k] = UnTrustIp_int
            if v[1]['parent'].find('Net') != -1:
                slogicpid = key
            else:
                slogicpid = key + 'mx' + v[1]['parent']

            res[v[0]] = {'id': v[0], 'name': v[1]['name'], 'parent': v[1]['parent'], 'type': '1', 'network': key,
                         'subtree': subtree, 'logicId': key + 'mx' + v[0], 'logicpid': slogicpid,
                         'issubnet': v[1]['issubnet']}
        tree_list = self.list_to_trees(res, 'parent', 'subtree', key)
        if tmp:
            run_function = lambda x, y: x if y in x else x + [y]
            tmp_list = reduce(run_function, [[], ] + tmp)
            tree_list.extend(tmp_list)
        return tree_list, UnTrustIpCount_dict

    def list(self, **kwargs):
        """
        获取IP树
        :param kwargs 参数字典
        """
        network_dict = self.db.IpNetwork_dict(**kwargs)
        if 'GroupId' in kwargs and kwargs['GroupId']:
            GroupId = kwargs['GroupId']
        else:
            GroupId = ''
        if 'id' in kwargs and kwargs['id']:
            id = kwargs['id']
        else:
            id = ''
        # 获取子网数量
        subnet_count_dict = self.db.GetIpNetnetCount(**kwargs)
        Groups = list()
        UnTrustIpCount = 0
        if network_dict:
            network_dict = sorted(network_dict.items(), key=lambda k: int(k[0][4:]), reverse=False)
            for v in network_dict:
                if 'group' in v[1]:
                    if 'SubNet' in v[1]:
                        subnet_list = v[1]['SubNet']
                    else:
                        subnet_list = None

                    data_list, UnTrustIpCount_dict = self.list_tree(v[1]['group'], subnet_list, v[0],
                                                                    subnet_count_dict[v[0]], GroupId, id)
                    UnTrustIpCount += sum(list(UnTrustIpCount_dict.values()))
                else:
                    data_list = list()
                    if 'SubNet' in v[1]:
                        for k, val in v[1]['SubNet'].items():
                            if k not in subnet_count_dict[v[0]]:
                                raise ParamsError(_('获取缓存%s失败' % k))
                            count_int = subnet_count_dict[v[0]][k]['UsedIpCount'] if k in subnet_count_dict[v[0]] else 0
                            UnTrustIp_int = subnet_count_dict[v[0]][k]['UnTrust']
                            label_str = val['label'] if val['label'] else k
                            data_list.append(
                                {'id': k, 'name': label_str, 'SubnetIp': val['SubnetIp'], 'type': '2',
                                 'parent': v[0], 'count': count_int, 'network': v[0], 'UnTrustIp': UnTrustIp_int,
                                 'logicId': v[0] + k, 'logicpid': v[0]})
                            UnTrustIpCount += UnTrustIp_int
                Groups.append({'id': v[0], 'name': v[1]['label'], 'parent': v[1]['parent'],
                               'state': v[1]['state'], 'type': '0', 'subtree': data_list, 'logicId': v[0],
                               'logicpid': v[1]['parent']})

        result = json.dumps(
            {'status': 'success', 'data': Groups, 'UnTrustIpCount': UnTrustIpCount,
             })
        return result

    def delete(self, *args, **kwargs):
        """
        删除网络组
        :param kwargs: 参数字典
        """
        return self.db.delete(**kwargs)

    def update(self, **kwargs):
        """
        网络更新
        :param kwargs: 参数字典
        :return:
        """
        return self.db.update(**kwargs)

    def ignore(self, **kwargs):
        """
        忽略网络
        :param kwargs: 参数字典
        :return:
        """
        return self.db.ignore(**kwargs)

    def retrieve(self, **kwargs):
        """
        回显数据
        :param kwargs: 参数字典
        :return:
        """
        return self.db.retrieve(**kwargs)

    def GroupSet(self, **kwargs):
        """
        网络组添加修改
        :param kwargs: 参数字典
        :return:
        """
        return self.db.GroupSet(**kwargs)

    def GroupDelete(self, **kwargs):
        """
        网络组删除
        :param kwargs: 参数字典
        :return:
        """
        return self.db.GroupDelete(**kwargs)

    def GroupIgnore(self, **kwargs):
        """
        网络组忽略
        :param kwargs: 参数字典
        :return:
        """
        return self.db.GroupIgnore(**kwargs)

    def IpShow(self, **kwargs):
        """
        IP列表显示
        :param kwargs: 参数字典
        :return:
        """
        if 'type' not in kwargs:
            raise ParamsError(_('类型不能为空'))
        # 获取网络数据
        if kwargs['type'] == '0':
            return self.db.GetIpNetworkInfo(**kwargs)
        # 获取指定网络或者分组数据
        elif kwargs['type'] == '1':
            dataCount_int, lReturn_list = self.db.GetNetworkOrGroupData(**kwargs)
            result = json.dumps(
                {'status': 'success', 'data': lReturn_list, 'page_index': kwargs['page_index'],
                 'pageSize': kwargs['page_size'],
                 'dataCount': dataCount_int, 'pageCount': math.ceil(dataCount_int / int(kwargs['page_size']))})
            return result

    def TsShow(self, **kwargs):
        """
        获取已关联的TS
        :param kwargs:
        :return:
        """
        ts = self.db.GetrelationTs(**kwargs)
        return ts

    def move(self, **kwargs):
        """
        移动组或者子网
        :param kwargs: 参数字典
        :return:
        """
        if 'type' not in kwargs:
            raise ParamsError(_('类型不能为空'))
        return self.db.move(**kwargs)

    def IgnoreTree(self, **kwargs):
        """
        忽略树
        :param kwargs: 参数字典
        :return:
        """
        return self.db.IgnoreTree(**kwargs)

    # def ip_info(self, **kwargs):
    #     """
    #     获取IP相关信息
    #     :param kwargs: 参数字典
    #     :return:
    #     """
    #     from bsmiddle import GetIPJson
    #     ip = self.db.ip_info(**kwargs)
    #     res = list()
    #     try:
    #         for val in ip:
    #             for v in val['subnet']:
    #                 res.append(eval(GetIPJson(kwargs['company'], val['network'], v)))
    #     except TypeError as e:
    #         raise CError('缓存中获取数据失败')
    #
    #     res_data = []
    #     for ip in res['data']:
    #
    #             flag = True  # 条件标志，当循环判断的条件有一个不满足时，标记改为False，即不满足
    #             ip['state'] = self.__check_state(ip)  # 根据条件判断当前ip状态
    #
    #             for k, v in query_data.items():
    #                 if str(ip[k]).find(str(v)) == -1:
    #                     flag = False
    #             if flag:
    #                 res_data.append(ip)
    #     elif res.get('data'):
    #         for ip in res['data']:
    #             ip['state'] = self.__check_state(ip)  # 根据条件判断当前ip状态
    #             res_data.append(ip)
